/**
 * 作者:hanbo
 * 日期:2018/11/1915:44
 * 描述:OpenGL矩阵操作中心
 */

import {mat4} from "../lib/gl-matrix";
import {Point} from "../geometry/Point";
import {EXTENDS_3857, getLevelDenominator, SCALE_CUSTOM, ZOOM_RADIO} from "./Constant";
import {Rectangle} from "../geometry/Rectangle";
import {Screen} from "../tool/Screen";

export class GLStateCenter {
    constructor(mapView) {
        this._mapView = mapView;
        this._projectionMatrix = mat4.create();//正交投影矩阵
        this._translateMatrix = mat4.create();//平移矩阵
        this._zoomMatrix = mat4.create();//缩放矩阵

        /**
         * 地图坐标中心默认为[0,0]
         * @type {Point}
         */
        this.center = new Point(0, 0);
        this.mapLevel=0;

    }

    /**
     * 设置正交投影参数
     * @param width
     * @param height
     */
    setOProjection(width = 0, height = 0) {
        let radio;
        if (width > height) {
            this.pixel_per_unit = height / 2;//每gl单位对应的像素数
            radio = width / height;
            mat4.ortho(this._projectionMatrix, -radio, radio, -1, 1, -1, 1);//1最近，-1最远
        } else {
            this.pixel_per_unit = width / 2;//每gl单位对应的像素数
            radio = height / width;
            mat4.ortho(this._projectionMatrix, -1, 1, -radio, radio, -1, 1);//1最近，-1最远
        }
        let dpm=Screen.getDPM();
        this.start_scale_d=dpm*EXTENDS_3857/this.pixel_per_unit;
        this._mapView._onMapReady();

    }

    /**
     * 获取当前投影
     * @returns {mat4|*}
     */
    getProjection() {
        let temp = mat4.create();
        mat4.multiply(temp, this._projectionMatrix, this._translateMatrix);
        let result = mat4.create();
        mat4.multiply(result, this._zoomMatrix, temp);
        return result;
    }

    /**
     * 设置矩阵缩放因子
     * @param scale 缩放比例
     */
    setScale(scale) {
        this._zoomMatrix[0] = scale;
        this._zoomMatrix[5] = scale;
    }

    zoom(dScale) {
        this._zoomMatrix[0] = this._zoomMatrix[0] + dScale*ZOOM_RADIO;
        this._zoomMatrix[5] = this._zoomMatrix[0];
    }

    /**
     * 通过鼠标移动的屏幕像素数计算偏移量
     * @param xPixel 水平方向像素偏移量
     * @param yPixel 竖直方向像素偏移量
     */
    move(xPixel, yPixel) {
        let d=this.pixel_per_unit*this._zoomMatrix[0];//使得不同等级缩放速度一致
        this.setTranslate(xPixel / d, yPixel / d);
    }

    /**
     * 设置平移参数
     * @param x 水平方向平移参数
     * @param y 竖直方向平移参数
     */
    setTranslate(x, y) {
        this._translateMatrix[12] = this._translateMatrix[12] + x;
        this._translateMatrix[13] = this._translateMatrix[13] + y;
        //更新地图中心坐标
        this.center.x = -this._translateMatrix[12] * EXTENDS_3857;
        this.center.y = -this._translateMatrix[13] * EXTENDS_3857;
        //触发地图移动事件
        this._mapView._eventCenter.onMove();
    }

    /**
     * 获取3857坐标系下的地图中心
     */
    getMapCenter() {
        return this.center;
    }

    /**
     * 获取当前坐标范围
     * @returns {Rectangle}
     */
    getMapExtend() {
        let x = this.center.x;
        let y = this.center.y;
        let radio,xMin,xMax,yMin,yMax,d2;
        let d1=EXTENDS_3857/this._zoomMatrix[0];
        if (this._projectionMatrix[0] == 1) {//此时为高大于宽
            radio =1 / this._projectionMatrix[5];
            d2=d1*radio;
            xMin=x-d1;
            xMax=x+d1;
            yMin=y-d2;
            yMax=y+d2;
        } else {//此时为宽大于高
            radio = 1 / this._projectionMatrix[0];
            d2=d1*radio;
            xMin=x-d2;
            xMax=x+d2;
            yMin=y-d1;
            yMax=y+d1;
        }

        //检查是否超出坐标系边界
        if(xMin<-EXTENDS_3857){xMin=-EXTENDS_3857}
        if(yMin<-EXTENDS_3857){yMin=-EXTENDS_3857}
        if(xMax>EXTENDS_3857){xMax=EXTENDS_3857}
        if(yMax>EXTENDS_3857){yMax=EXTENDS_3857}
        return new Rectangle(xMin,yMin,xMax,yMax);
    }

    /**
     * 获取比例尺分母
     */
    getScaleDenominator(){
        //起始比例尺分母/缩放比例
        return this.start_scale_d/ this._zoomMatrix[0];
    }

    /**
     * 获取当前地图等级
     * @returns {number}
     */
    getMapLevel(){
      return this.mapLevel;
    }

    /**
     * 获取比例尺分母对应的缩放因子
     * @param denominator {number} 比例尺分母
     * @returns {number} 缩放因子
     */
    getScaleFactor(denominator){
        return this.start_scale_d/denominator;
    }

    /**
     * 设置比例尺分母
     * @param denominator {number} 比例尺分母
     */
    setDenominator(denominator){
        this.setScale(this.getScaleFactor(denominator));
        this._mapView._eventCenter.onZoomEnd();
    }

    /**
     * 设置当前地图等级
     * @param level {number}
     */
    setLevel(level){
       this.mapLevel=level;
       this.setDenominator(getLevelDenominator(level));
    }

    /**
     * 缩小一个等级
     */
    zoomOut(){
        if(this.mapLevel<this._mapView.maxLevel){
            this.setLevel(this.mapLevel-1)
        }
    }

    /**
     * 放大一个等级
     */
    zoomIn(){
        if(this.mapLevel<this._mapView.maxLevel){
            this.setLevel(this.mapLevel+1)
        }
    }

    /**
     * 获取坐标1米对应的像素值
     */
    getPixel_per_Meter(){
       return this.pixel_per_unit*this._zoomMatrix[0]/EXTENDS_3857;
    }

    getUnit_per_Pixel(){
        return 1/(this.pixel_per_unit*this._zoomMatrix[0])
    }
}